package com.ruoyi.indicators.controller;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.indicators.domain.Indicators;
import com.ruoyi.indicators.service.IIndicatorsService;
import com.ruoyi.operators.service.IOperatorsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.text.DecimalFormat;
import java.util.*;

/**
 * 指标管理Controller
 *
 * @author ruoyi
 * @date 2023-05-13
 */
@RestController
@RequestMapping("/indicators/manage")
public class IndicatorsController extends BaseController {
    @Autowired
    private IIndicatorsService indicatorsService;
    @Autowired
    private IOperatorsService operatorsService;

    /**
     * 查询指标管理列表
     */
    @PreAuthorize("@ss.hasPermi('indicators:manage:list')")
    @GetMapping("/list")
    public TableDataInfo list(Indicators indicators) {
        startPage();
        List<Indicators> list = indicatorsService.selectIndicatorsList(indicators);
        return getDataTable(list);
    }

    /**
     * 导出指标管理列表
     */
    @PreAuthorize("@ss.hasPermi('indicators:manage:export')")
    @Log(title = "指标管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Indicators indicators) {
        List<Indicators> list = indicatorsService.selectIndicatorsList(indicators);
        ExcelUtil<Indicators> util = new ExcelUtil<Indicators>(Indicators.class);
        util.exportExcel(response, list, "指标管理数据");
    }

    /**
     * 获取指标管理详细信息
     */
    @PreAuthorize("@ss.hasPermi('indicators:manage:query')")
    @GetMapping(value = "/{indicatorsId}")
    public AjaxResult getInfo(@PathVariable("indicatorsId") Integer indicatorsId) {
        return success(indicatorsService.selectIndicatorsByIndicatorsId(indicatorsId));
    }

    /**
     * 新增指标管理
     */
    @PreAuthorize("@ss.hasPermi('indicators:manage:add')")
    @Log(title = "指标管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody Indicators indicators) {
        if (indicatorsService.selectIndicatorsByIndicatorsId(indicators.getIndicatorsId()) != null) {
            return error("已存在相同指标ID，请重新输入！");
        }
        return toAjax(indicatorsService.insertIndicators(indicators));
    }

    /**
     * 修改指标管理
     */
    @PreAuthorize("@ss.hasPermi('indicators:manage:edit')")
    @Log(title = "指标管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Indicators indicators) {
        indicatorsService.updateIndicators(indicators);
        List<Map<String, Object>> l = all();
        return toAjax(indicatorsService.updateIndicators(indicators));
    }

    /**
     * 删除指标管理
     */
    @PreAuthorize("@ss.hasPermi('indicators:manage:remove')")
    @Log(title = "指标管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{indicatorsIds}")
    public AjaxResult remove(@PathVariable Integer[] indicatorsIds) {
        indicatorsService.updateFather(indicatorsIds);
        /*用不到了好像

        List<Indicators> allIndicators = indicatorsService.selectAllIndicators();
        Map<Integer,Integer> rootMap  = new HashMap<>();
        Map<Integer,Integer> nodeMap  = new HashMap<>();
        boolean flag = false;
        for (Indicators i : allIndicators) {                    //遍历所有节点
            if(i.getIndicatorsId().equals(i.getFather())){      //自身节点值与父节点值相同就是根节点
                rootMap.put(i.getIndicatorsId(),i.getIndicatorsId());
            }
            else{
                nodeMap.put(i.getIndicatorsId(), i.getFather());
            }
        }

         */


        // List<Integer> newList = new ArrayList<>();

        // for (int i : indicatorsIds) {
        //  if(rootMap.containsKey(i)){//根节点

        //    indicatorsIds.
        //}
        // else{
        //  List<Integer> childList = findChild(i);


        //}
        //}

        return toAjax(indicatorsService.deleteIndicatorsByIndicatorsIds(indicatorsIds));
    }

    /**
     * 获得全部列表消息
     */
    // @PreAuthorize("@ss.hasPermi('indicators:manage:all')")
    @GetMapping("/all")
    public List<Map<String, Object>> all() {
        List<Indicators> allIndicators = indicatorsService.selectAllIndicators();
        List<Map<String, Object>> all = new ArrayList<Map<String, Object>>();


        ////////////////////////////////// calculate begin

        List<Integer> rootList = new ArrayList<Integer>();            // 统计所有根节点
        Set<Integer> rootOnlyNode = new HashSet<Integer>();    // 处理只有没有子节点的节点
        Set<Integer> rootOnly = new HashSet<Integer>();        // 处理只有自己的根节点
        // 获取根节点列表
        for (Indicators i : allIndicators) {                    // 遍历所有节点
            if (i.getIndicatorsId().equals(i.getFather())) {      // 自身节点值与父节点值相同就是根节点
                rootList.add(i.getIndicatorsId());
            }
        }

        // int loopControl = 0;
        Map<Integer, Integer> mpTreeJudge = new HashMap<Integer, Integer>();

        // 计算每棵树权值
        for (int i : rootList) {
            calTree(i, allIndicators, rootOnlyNode, mpTreeJudge);
        }
        /*单节点控制（已废弃）
        for (int i : rootList) {
            if (rootOnlyNode.contains(i)) {// 是根节点而且没有子节点
                rootOnly.add(i);
            }
        }
         */

        // 精度控制，确保最多6位小数
        DecimalFormat df = new DecimalFormat("#.000000");


        // allIndicators 赋值回原数据库
        for (Indicators i : allIndicators) {
            String formatted = df.format(i.getValue());
            double result = Double.parseDouble(formatted);
            i.setValue(result);
            indicatorsService.updateValue(i);
        }

        /////////////////////////////////// calculate end

        // 发送数据
        for (Indicators i : allIndicators) {
            //if (rootOnly.contains(i.getIndicatorsId())) continue;
            Map<String, Object> mp = new HashMap<String, Object>();
            mp.put("id", i.getIndicatorsId());
            mp.put("text", i.getIndicatorsName());
            mp.put("father", i.getFather());
            mp.put("oper", i.getOperator());
            mp.put("weight", i.getWeight());
            mp.put("value", i.getValue());
            all.add(mp);
        }


        return all;
    }

    /**
     * 批量设置父节点
     */
    // @PreAuthorize("@ss.hasPermi('indicators:manage:fa')")
    @Log(title = "更新父节点", businessType = BusinessType.UPDATE)
    @PutMapping("/{indicatorsIds}")
    public AjaxResult fa(@PathVariable Integer[] indicatorsIds, @RequestBody Indicators indicators) {
        List<Integer> allId = indicatorsService.selectAllFather();

        for (Integer i : allId) {
            System.out.println(i);
            if (i == indicators.getFather()) {
                indicatorsService.setFather(indicatorsIds, indicators.getFather());
                List<Map<String, Object>> l = all();
                return toAjax(indicatorsService.setFather(indicatorsIds, indicators.getFather()));
            }
        }
        return error("不存在该节点ID");
    }

    //////////////////////////////////// calculate tools

    // function 1，遍历得到该节点的所有子节点list
    // input: 父节点ID
    // output: 子节点ID列表
    public List<Integer> findChild(int fatherId) {
        List<Integer> childIdList = new ArrayList<>();
        List<Indicators> allIndicators = indicatorsService.selectAllIndicators();
        for (Indicators i : allIndicators) {
            if (i.getFather().equals(fatherId) && i.getIndicatorsId() != fatherId) {
                childIdList.add(i.getIndicatorsId());
            }
        }
        return childIdList;
    }

    // function 2，递归计算权值
    // input: 父节点ID
    // output: 以当前节点为树的值
    public double calTree(int fatherId, List<Indicators> allIndicators, Set<Integer> rootOnlyNode, Map<Integer, Integer> mpTreeJudge) {
        for (Indicators i : allIndicators) {
            if (fatherId == i.getIndicatorsId()) {        // 找到该节点
                if (mpTreeJudge.containsKey(fatherId)) {
                    System.out.println("出现环状结构，计算终止");
                    return 0;
                } else mpTreeJudge.put(fatherId, 1);
                i.setValue(i.getWeight());          // 权值就是权重
                double calEndValue = i.getWeight();


                List<Integer> childList = findChild(fatherId);

                if (childList.size() == 0) {   // 该节点没有子节点，是叶子节点
                    rootOnlyNode.add(i.getIndicatorsId());
                    return calEndValue;
                }


                // 不是叶子节点，将子节点计算出来就就行
                // 解析表达式，例如y+x

                ExpressionParser parser = new SpelExpressionParser();
                StandardEvaluationContext context = new StandardEvaluationContext();


                for (Integer integer : childList) {
                    context.setVariable("calEndValue", calEndValue);
                    double childValue = calTree(integer, allIndicators, rootOnlyNode, mpTreeJudge);
                    context.setVariable("childValue", childValue);
                    String o = operatorsService.selectOperatorsByName(i.getOperator()).getCalculate();
                    if (o == null) {
                        o = "y+x";
                    }
                    try {
                        //System.out.println(o);
                        o = o.replaceAll("y", "#calEndValue ").replaceAll("x", " #childValue");
                        Expression expression = parser.parseExpression(o);
                        System.out.println(o);
                        // Expression expression = parser.parseExpression("#calEndValue " + o + " #childValue");
                        calEndValue = expression.getValue(context, Double.class);
                    } catch (Exception e) {
                        Expression expression=parser.parseExpression("#calEndValue + #childValue");
                        calEndValue=expression.getValue(context, Double.class);
                        System.out.println("表达式计算出错：" + e.getMessage());
                        // return 0;
                    }
                }

                i.setValue(calEndValue);
                System.out.println(calEndValue);
                return calEndValue;

            }
        }
        return 0;
    }


    /**
     * 新增指标管理(树)
     */
    @Log(title = "指标管理", businessType = BusinessType.INSERT)
    @GetMapping("/add/{father}")
    public AjaxResult addByTree(@PathVariable("father") String father) {
        Integer fatherId = Integer.parseInt(father);
        Integer maxId = indicatorsService.getMaxId();
        if(maxId == null)maxId = 0;
        if(fatherId == 0){
            fatherId = maxId+1;
        }
        Indicators indicators1 = new Indicators();
        indicators1.setIndicatorsId(maxId + 1);
        indicators1.setIndicatorsName("默认节点名称");
        indicators1.setFather(fatherId);
        indicators1.setValue(0.0);
        indicators1.setWeight(0.0);
        indicators1.setOperator("加法");

        return toAjax(indicatorsService.insertIndicators(indicators1));
    }
}
